package com.cskaoyan.market.controller;

import com.cskaoyan.market.db.domain.MarketAdmin;
import com.cskaoyan.market.service.MarketAdminService;
import com.cskaoyan.market.service.impl.MarketAdminServiceImpl;
import com.cskaoyan.market.util.JacksonUtil;
import com.cskaoyan.market.util.ResponseUtil;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.lang3.StringUtils;

import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @ClassName AdminAuthController
 * @Description: TODO
 * @Author 远志 zhangsong@cskaoyan.onaliyun.com
 * @Date 2023/5/5 10:18
 * @Version V1.0
 **/
@WebServlet("/admin/auth/*")
public class AdminAuthController extends HttpServlet {

    private MarketAdminService adminService = new MarketAdminServiceImpl();

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // /admin/auth/login这个请求会进入到doPost方法中，但是后续其他方法也可能会进入到当前方法中，所以，我们首先进行方法的分发，主要是将/admin/auth/去掉，通过字符串的比对，分发到不同的方法中去
        String requestURI = req.getRequestURI();
        String op = requestURI.replace(req.getContextPath() + "/admin/auth/", "");
        if("login".equals(op)){
            login(req, resp);
        }
        
    }

    /**
     * 登录的业务逻辑：
     * 1.获取请求参数，但是记住不可以使用request.getparameter来获取
     * 2.处理具体的业务逻辑
     * 3.返回响应体---和公网一致即可
     * @param req
     * @param resp
     */
    private void login(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        //System.out.println("login");
        //请求参数位于请求体中，所以我们需要自己主动的去解析请求体
        ServletInputStream inputStream = req.getInputStream();
        //ByteArrayOutputStream和FileOutputStream的区别就是一个写出到数组，一个写出到文件，除此之外，操作上完全一模一样
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        int length = 0;
        byte[] bytes = new byte[1024];
        while ((length = inputStream.read(bytes)) != -1){
            byteArrayOutputStream.write(bytes, 0, length);
        }
        //数组里面的数据转换成字符串
        // {"username":"admin123","password":"admin123"}
        //处理起来有两种方式
        //方式一：1.定义一个对象，将json字符串转换成对象，但是这种处理方式会占用一个对象
        String requestBody = byteArrayOutputStream.toString("utf-8");
        //方式二：2.jacksonUtiis，parseString---取出对应的属性值，比如username、password；如果字段不是特别多的情况下，我们更为推荐大家使用下面这种方式
        String username = JacksonUtil.parseString(requestBody, "username");
        String password = JacksonUtil.parseString(requestBody, "password");
        //获取完请求参数之后，怎么办？
        //首先做一些校验----放在controller中去做更为合适一些
        if(StringUtils.isEmpty(username) || StringUtils.isEmpty(password)){
            //TODO
            Object o = ResponseUtil.badArgument();
            resp.getWriter().println(JacksonUtil.getObjectMapper().writeValueAsString(o));
            return;
        }
        //根据size是否是1还是0判断用户是否登录成功
        List<MarketAdmin> marketAdmins = adminService.login(username, password);
        //根据code的值，返回不同的响应结果
        if(marketAdmins.size() == 0){
            //用户名、密码错误
            Object o = ResponseUtil.wrongUsernameOrPassword();
            resp.getWriter().println(JacksonUtil.getObjectMapper().writeValueAsString(o));
            return;
        }
        //登录成功---返回的时候要保证你的响应和公网上面的响应格式(json结构、字段的名称)是一致的
//        {
//            "errno": 0,
//                "data": {
//            "adminInfo": {
//                "nickName": "admin123",
//                        "avatar": "https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif"
//            },
//            "token": "e03fefef-27d2-4981-ae36-c5b0c06a81c5"
//        },
//            "errmsg": "成功"
//        }
        //TODO
        Map<String, Object> result = new HashMap<>();
        Map<String, String> adminInfoMap = new HashMap<>();
        adminInfoMap.put("nickName", username);
        adminInfoMap.put("avatar",marketAdmins.get(0).getAvatar());
        result.put("adminInfo", adminInfoMap);
        //登录成功之后的凭证可以使用session的编号来充当
        HttpSession session = req.getSession();
        session.setAttribute("admin", marketAdmins.get(0));
        String id = session.getId();
        result.put("token", id);
        Object ok = ResponseUtil.ok(result);
        //哪个方法可以设置响应体？？
        ObjectMapper objectMapper = JacksonUtil.getObjectMapper();
        String s = objectMapper.writeValueAsString(ok);
        resp.getWriter().println(s);
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String requestURI = req.getRequestURI();
        String op = requestURI.replace(req.getContextPath() + "/admin/auth/", "");
        if("info".equals(op)){
            info(req, resp);
        }
    }

    /**
     * 管理员个人中心接口
     * 三步走：
     * 1.获取接收请求参数-无
     * 2.处理具体的业务逻辑---只需要提供3所需要的数据即可
     * 3.返回响应
     * @param req
     * @param resp
     */
    private void info(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        Map<String, Object> result = new HashMap<>();
        HttpSession session = req.getSession();
        MarketAdmin admin = (MarketAdmin) session.getAttribute("admin");
        //关于roles以及perms是属于权限管理部分的内容，shiro，直接固定写即可
        result.put("roles", new String[]{"超级管理员"});
        result.put("name", admin.getUsername());
        result.put("perms", new String[]{"*"});
        result.put("avatar", admin.getAvatar());
        Object ok = ResponseUtil.ok(result);
        resp.getWriter().println(JacksonUtil.getObjectMapper().writeValueAsString(ok));

    }
}
